﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Sausage.Common;
using Sausage.Web.Code;
using Sausage.Web.DataModel;
using Sausage.Web.Models;
using Telerik.Web.Mvc;

namespace Sausage.Web.Domain
{
    public class InstructionHelper
    {
        public static Instruction GetInstructionByID(Guid instructionID)
        {
            using (SausageEntities context = new SausageEntities())
            {
                return
                    context.Instruction.Include("Receivers").FirstOrDefault(
                        item => item.InstructionID == instructionID);
            }
        }

        public static void UpdateInstruction(InstructionListRow data)
        {
            using (var context = new SausageEntities())
            {
                var instruction = context.Instruction.FirstOrDefault(item => item.InstructionID == data.InstructionID);
                if (instruction == null)
                    return;

                instruction.Title = data.Title;
                instruction.Content = data.Content;
                instruction.PostType = data.PostType;
                instruction.InstructionType = data.InstructionType;
                instruction.Receivers.Clear();
                context.SaveChanges();
            }

            using (var context = new SausageEntities())
            {
                var instruction = context.Instruction.FirstOrDefault(item => item.InstructionID == data.InstructionID);
                
                //set the receiver.
                if (Helper.CurrentPrincipal.IsDistrictOrganization)
                {
                    //send message from the district
                    if (data.PostType == (int)PostTypeEnum.ToPartial)
                    {
                        //To partial so need to save the reserver.
                        foreach (var item in data.Receivers)
                        {
                            var organization = new Organization()
                            {
                                OrganizationID = item
                            };
                            context.CreateObjectSet<Organization>().Attach(organization);
                            instruction.Receivers.Add(organization);
                        }
                    }
                    //To all do not need to save the reserver.
                }
                else
                {
                    //send it from the partition
                    //the receiver is the district.
                    var organization = new Organization()
                    {
                        OrganizationID = OrganizationHelper.DistrictOrganization
                    };

                    context.CreateObjectSet<Organization>().Attach(organization);
                    instruction.Receivers.Add(organization);
                }

                context.SaveChanges();
            }
        }

        public static void DeleteInstruction(InstructionListRow data)
        {
            using (var context = new SausageEntities())
            {
                var instruction =
                    context.Instruction.Where(item => item.InstructionID == data.InstructionID).FirstOrDefault();

                if (instruction != null)
                {
                    instruction.Receivers.Clear();
                    context.SaveChanges();
                }
            }

            using (var context = new SausageEntities())
            {
                var instruction =
                    context.Instruction.Where(item => item.InstructionID == data.InstructionID).FirstOrDefault();

                if (instruction != null)
                {
                    context.DeleteObject(instruction);
                    context.SaveChanges();
                }
            }
        }

        public static void ExecuteSubmit(Guid[] instructions)
        {
            if (null != instructions && instructions.Length > 0)
            {
                using (var context = new SausageEntities())
                {
                    var list = context.Instruction.Where(item => instructions.Contains(item.InstructionID)).ToList();

                    foreach (var entity in list)
                    {
                        entity.State = (int)DataStateEnum.Submitted;
                    }
                    context.SaveChanges();
                }
            }
        }

        public static void CreateInstruction(InstructionListRow data)
        {
            using (var context = new SausageEntities())
            {
                var instruction = new Instruction()
                {
                    InstructionID = Guid.NewGuid(),
                    CreateDate = DateTime.Now,
                    Creater = Helper.CurrentPrincipal.User.UserName,
                    InstructionType = data.InstructionType,
                    Title = data.Title,
                    PostType = data.PostType,
                    State = (int)DataStateEnum.Unsubmit,
                    Content = data.Content,
                };

                context.AddToInstruction(instruction);

                //set the receiver.
                if (Helper.CurrentPrincipal.IsDistrictOrganization)
                {
                    //send message from the district
                    if (data.PostType == (int)PostTypeEnum.ToPartial)
                    {
                        //To partial so need to save the reserver.
                        foreach (var item in data.Receivers)
                        {
                            var organization = new Organization()
                                                   {
                                                       OrganizationID = item
                                                   };
                            context.CreateObjectSet<Organization>().Attach(organization);
                            instruction.Receivers.Add(organization);
                        }
                    }
                    //To all do not need to save the reserver.
                }
                else
                {
                    //send it from the partition
                    //the receiver is the district.
                    var organization = new Organization()
                    {
                        OrganizationID = OrganizationHelper.DistrictOrganization
                    };

                    context.CreateObjectSet<Organization>().Attach(organization);
                    instruction.Receivers.Add(organization);
                }

                context.SaveChanges();
            }
        }

        public static GridModel<object> Select(JosnPagingQueryModel query)
        {
            using (var context = new SausageEntities())
            {
                if (query.SortModel.Length == 0) //default sort.
                    query.SortModel = new JosnQuerySortModel[] { new JosnQuerySortModel() { property = "CreateDate", direction = "DESC" } };

                var organization = OrganizationHelper.GetAllowedOrganizationList();


                return
                    QueryInstruction(
                        context.InstructionReceiverView.Where(item =>
                            (
                             (item.PostType == (int)PostTypeEnum.ToAll || (item.ReceiverID.HasValue && organization.Contains(item.ReceiverID.Value)))
                             && item.State == (int)DataStateEnum.Submitted)
                            ).Distinct(),
                         query);
            }
        }

        public static GridModel<object> SubmitSelect(JosnPagingQueryModel query)
        {
            using (var context = new SausageEntities())
            {
                if (query.SortModel.Length == 0) //default sort.
                    query.SortModel = new JosnQuerySortModel[] { new JosnQuerySortModel() { property = "CreateDate", direction = "DESC" } };

                return
                    QueryInstruction(
                        context.InstructionReceiverView.Where(
                            item =>
                            item.State == (int)MaintainDataStateEnum.Unsubmit).Distinct(),
                        query);
            }
        }

        private static GridModel<object> QueryInstruction(IQueryable<InstructionReceiverView> source, JosnPagingQueryModel query)
        {
            var result = UIHelper.GetGridModelFromQueryModel<InstructionReceiverView>(
                source,
                query.page,
                query.limit,
                GetSortDescriptorFromQueryModel(query.SortModel),
                GetSearchFilterFromQueryModel(query.FilterModel));

            var list = result.Data.Select(item => new
            {
                item.InstructionID,
                item.InstructionType,
                item.Title,
                item.PostType,
                item.State,
                item.Creater,
                item.CreateDate
            }).ToList();

            return new GridModel<object>()
            {
                Aggregates = result.Aggregates,
                Data = list,
                Total = result.Total
            };
        }

        private static List<IFilterDescriptor> GetSearchFilterFromQueryModel(IEnumerable<JosnQueryFilterModel> filterModels)
        {
            var filterList = new List<IFilterDescriptor>();
            foreach (var item in filterModels)
            {
                if (string.IsNullOrEmpty(item.value))
                    continue;

                if (item.property.EndsWith("ID", StringComparison.InvariantCultureIgnoreCase))
                {
                    var targetID = Guid.Parse(item.value);
                    if (targetID != Guid.Empty)
                        filterList.Add(new FilterDescriptor(item.property, FilterOperator.IsEqualTo, targetID));
                }
                else //other filter.
                    filterList.Add(new FilterDescriptor(item.property, FilterOperator.Contains, item.value));
            }
            return filterList;
        }

        private static List<SortDescriptor> GetSortDescriptorFromQueryModel(IEnumerable<JosnQuerySortModel> sortModels)
        {
            //convert the sort description.
            var sortList = new List<SortDescriptor>();
            foreach (var item in sortModels)
            {
                var descriptor = new SortDescriptor()
                {
                    Member = item.property,
                    SortDirection =
                        item.direction.ToLower() == "desc"
                            ? ListSortDirection.Descending
                            : ListSortDirection.Ascending
                };

                if (descriptor.Member == "Organization")
                    descriptor.Member = "Organization.OrganizationName";

                sortList.Add(descriptor);
            }
            return sortList;
        }

    }
}
